<?php

namespace helper\union\sdk;

class CertUtil
{

    private static $signCerts = array();
    private static $encryptCerts = array();
    private static $verifyCerts = array();
    private static $verifyCerts510 = array();

    private static $company = '中国银联股份有限公司';

    private static function cert()
    {
        $certs         = new \stdClass();
        $certs->cert   = '';
        $certs->certId = '';
        $certs->key    = '';
        return $certs;
    }

    private static function initSignCert($certPath, $certPwd)
    {
        $logger = LogUtil::getLogger();
        $logger->LogInfo("读取签名证书……");

        $pkcs12certdata = file_get_contents($certPath);
        if ($pkcs12certdata === false) {
            $logger->LogInfo($certPath . "file_get_contents fail。");
            return;
        }

        if (openssl_pkcs12_read($pkcs12certdata, $certs, $certPwd) == FALSE) {
            $logger->LogInfo($certPath . ", pwd[" . $certPwd . "] openssl_pkcs12_read fail。");
            return;
        }

        $cert     = self::cert();
        $x509data = $certs ['cert'];

        if (!openssl_x509_read($x509data)) {
            $logger->LogInfo($certPath . " openssl_x509_read fail。");
        }
        $certdata     = openssl_x509_parse($x509data);
        $cert->certId = $certdata ['serialNumber'];
        $cert->key    = $certs ['pkey'];
        $cert->cert   = $x509data;

        $logger->LogInfo("签名证书读取成功，序列号：" . $cert->certId);
        CertUtil::$signCerts[$certPath] = $cert;
    }

    public static function getSignKeyFromPfx($certPath = null, $certPwd = null)
    {
        if ($certPath == null) {
            $certPath = SDKConfig::getSDKConfig()->signCertPath;
            $certPwd  = SDKConfig::getSDKConfig()->signCertPwd;
        }

        if (!array_key_exists($certPath, CertUtil::$signCerts)) {
            self::initSignCert($certPath, $certPwd);
        }
        return CertUtil::$signCerts[$certPath]->key;
    }

    public static function getSignCertIdFromPfx($certPath = null, $certPwd = null)
    {

        if ($certPath == null) {
            $certPath = SDKConfig::getSDKConfig()->signCertPath;
            $certPwd  = SDKConfig::getSDKConfig()->signCertPwd;
        }

        if (!array_key_exists($certPath, CertUtil::$signCerts)) {
            self::initSignCert($certPath, $certPwd);
        }
        return CertUtil::$signCerts[$certPath]->certId;
    }

    private static function initEncryptCert($cert_path)
    {
        $logger = LogUtil::getLogger();
        $logger->LogInfo("读取加密证书……");

        $x509data = file_get_contents($cert_path);
        if ($x509data === false) {
            $logger->LogInfo($cert_path . " file_get_contents fail。");
            return;
        }

        if (!openssl_x509_read($x509data)) {
            $logger->LogInfo($cert_path . " openssl_x509_read fail。");
            return;
        }

        $cert                               = self::cert();
        $certdata                           = openssl_x509_parse($x509data);
        $cert->certId                       = $certdata ['serialNumber'];
        $cert->key                          = $x509data;
        CertUtil::$encryptCerts[$cert_path] = $cert;
        $logger->LogInfo("加密证书读取成功，序列号：" . $cert->certId);
    }



    public static function getEncryptCertId($cert_path = null)
    {
        if ($cert_path == null) {
            $cert_path = SDKConfig::getSDKConfig()->encryptCertPath;
        }
        if (!array_key_exists($cert_path, CertUtil::$encryptCerts)) {
            self::initEncryptCert($cert_path);
        }
        if (array_key_exists($cert_path, CertUtil::$encryptCerts)) {
            return CertUtil::$encryptCerts[$cert_path]->certId;
        }
        return false;
    }

    public static function getEncryptKey($cert_path = null)
    {
        if ($cert_path == null) {
            $cert_path = SDKConfig::getSDKConfig()->encryptCertPath;
        }
        if (!array_key_exists($cert_path, CertUtil::$encryptCerts)) {
            self::initEncryptCert($cert_path);
        }
        if (array_key_exists($cert_path, CertUtil::$encryptCerts)) {
            return CertUtil::$encryptCerts[$cert_path]->key;
        }
        return false;
    }

    private static function initVerifyCerts($cert_dir = null)
    {

        if ($cert_dir == null) {
            $cert_dir = SDKConfig::getSDKConfig()->validateCertDir;
        }

        $logger = LogUtil::getLogger();
        $logger->LogInfo('验证签名证书目录 :>' . $cert_dir);
        $handle = opendir($cert_dir);
        if (!$handle) {
            $logger->LogInfo('证书目录 ' . $cert_dir . '不正确');
            return;
        }

        while ($file = readdir($handle)) {
            clearstatcache();
            $filePath = $cert_dir . '/' . $file;
            if (is_file($filePath)) {
                if (pathinfo($file, PATHINFO_EXTENSION) == 'cer') {

                    $x509data = file_get_contents($filePath);
                    if ($x509data === false) {
                        $logger->LogInfo($filePath . " file_get_contents fail。");
                        continue;
                    }
                    if (!openssl_x509_read($x509data)) {
                        $logger->LogInfo($certPath . " openssl_x509_read fail。");
                        continue;
                    }

                    $cert                                 = self::cert();
                    $certdata                             = openssl_x509_parse($x509data);
                    $cert->certId                         = $certdata ['serialNumber'];
                    $cert->key                            = $x509data;
                    CertUtil::$verifyCerts[$cert->certId] = $cert;
                    $logger->LogInfo($filePath . "读取成功，序列号：" . $cert->certId);
                }
            }
        }
        closedir($handle);
    }

    public static function getVerifyCertByCertId($certId)
    {
        $logger = LogUtil::getLogger();
        if (count(CertUtil::$verifyCerts) == 0) {
            self::initVerifyCerts();
        }
        if (count(CertUtil::$verifyCerts) == 0) {
            $logger->LogInfo("未读取到任何证书……");
            return null;
        }
        if (array_key_exists($certId, CertUtil::$verifyCerts)) {
            return CertUtil::$verifyCerts[$certId]->key;
        } else {
            $logger->LogInfo("未匹配到序列号为[" . certId . "]的证书");
            return null;
        }
    }
}





    